home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / workbench / directoryopus4 / dopus4_src / library / filereq.c < prev    next >
C/C++ Source or Header  |  2000-03-11  |  36KB  |  1,013 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "dopuslib.h"
  32. #include "filereq.h"
  33.  
  34. static struct PropInfo
  35.     defaultprop={PROPBORDERLESS|FREEVERT,0,0,0,0xffff};
  36. static struct Image
  37.     defaultimage={0,0,8,22,1,NULL,0,1,NULL};
  38.  
  39. static struct IntuiText
  40.     defaulttext[6]={
  41.         {1,0,JAM1,0,0,NULL,(UBYTE *)"File",NULL},
  42.         {1,0,JAM1,0,0,NULL,(UBYTE *)"Drawer",NULL},
  43.         {1,0,JAM1,0,2,NULL,(UBYTE *)"Accept",NULL},
  44.         {1,0,JAM1,0,2,NULL,(UBYTE *)"Cancel",NULL},
  45.         {1,0,JAM1,0,2,NULL,(UBYTE *)"Parent",NULL},
  46.         {1,0,JAM1,0,2,NULL,(UBYTE *)"Drives",NULL}};
  47.  
  48. static struct Gadget
  49.     defaultgadgets[9]={
  50.         {NULL,64,47,240,8,GADGHCOMP,RELVERIFY|TOGGLESELECT,STRGADGET,
  51.             NULL,NULL,NULL,NULL,NULL,FILENAME,NULL},
  52.         {NULL,64,34,240,8,GADGHCOMP,RELVERIFY|TOGGLESELECT,STRGADGET,
  53.             NULL,NULL,NULL,NULL,NULL,DRAWERNAME,NULL},
  54.         {NULL,8,59,132,12,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
  55.             NULL,NULL,NULL,OKAY,NULL},
  56.         {NULL,176,59,132,12,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
  57.             NULL,NULL,NULL,CANCEL,NULL},
  58.         {NULL,292,14,16,8,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
  59.             NULL,NULL,NULL,NULL,NULL,FILENAMEUP,NULL},
  60.         {NULL,292,22,16,8,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
  61.             NULL,NULL,NULL,NULL,NULL,FILENAMEDOWN,NULL},
  62.         {NULL,8,14,132,12,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
  63.             NULL,NULL,NULL,PARENT,NULL},
  64.         {NULL,176,14,132,12,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
  65.             NULL,NULL,NULL,DRIVES,NULL},
  66.         {NULL,296,30,8,22,GADGHNONE,GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,PROPGADGET,
  67.             NULL,NULL,NULL,NULL,NULL,FILENAMEPOS,NULL}};
  68.  
  69. static struct NewWindow defaultwindow={
  70.     15,25,316,115,0,1,IDCMP_GADGETUP|IDCMP_GADGETDOWN|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS,
  71.     WFLG_SMART_REFRESH|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_DRAGBAR,
  72.     NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  73.  
  74. extern char nullstring[];
  75.  
  76. __saveds DoFileRequest(register struct DOpusFileReq *freq __asm("a0"))
  77. {
  78.     struct Library *AslBase;
  79.  
  80.     if (freq->dirbuf[0] && (CheckExist(freq->dirbuf,NULL)<0)) {
  81.         char *ptr;
  82.         if (ptr=BaseName(freq->dirbuf)) {
  83.             if (freq->filebuf) {
  84.                 int a;
  85.  
  86.                 LStrnCpy(freq->filebuf,ptr,30);
  87.                 a=strlen(freq->filebuf);
  88.                 if (freq->filebuf[a-1]=='/') freq->filebuf[a-1]=0;
  89.             }
  90.             *ptr=0;
  91.         }
  92.     }
  93.  
  94.     if ((AslBase=OpenLibrary("asl.library",0))) {
  95.         struct TagItem asltags[10];
  96.         struct FileRequester *fr;
  97.         int font,res,a;
  98.         char initialfont[40],*ptr;
  99.         APTR request;
  100.  
  101.         for (a=0;a<10;a++) {
  102.             asltags[a].ti_Tag=TAG_SKIP;
  103.             asltags[a].ti_Data=0;
  104.         }
  105.         asltags[9].ti_Tag=TAG_END;
  106.  
  107.         if (freq->flags&DFRF_FONT) font=1;
  108.         else font=0;
  109.  
  110.         if (freq->title) {
  111.             asltags[0].ti_Tag=ASL_Hail;
  112.             asltags[0].ti_Data=(ULONG)freq->title;
  113.         }
  114.  
  115.         asltags[1].ti_Tag=ASL_Window;
  116.         asltags[1].ti_Data=(ULONG)((freq->window)?freq->window:IntuitionBase->ActiveWindow);
  117.  
  118.         if (freq->x>0) {
  119.             asltags[2].ti_Tag=ASL_LeftEdge;
  120.             asltags[2].ti_Data=freq->x;
  121.         }
  122.  
  123.         if (freq->y>0) {
  124.             asltags[3].ti_Tag=ASL_TopEdge;
  125.             asltags[3].ti_Data=freq->y;
  126.         }
  127.  
  128.         asltags[4].ti_Tag=ASL_Height;
  129.         asltags[4].ti_Data=freq->lines*14;
  130.  
  131.         if (font) {
  132.             if (ptr=BaseName(freq->dirbuf)) {
  133.                 strcpy(initialfont,ptr);
  134.                 a=strlen(initialfont);
  135.                 if (initialfont[a-1]=='/') initialfont[a-1]=0;
  136.             }
  137.             else initialfont[0]=0;
  138.             asltags[5].ti_Tag=ASLFO_InitialName;
  139.             asltags[5].ti_Data=(ULONG)initialfont;
  140.             asltags[6].ti_Tag=ASLFO_InitialSize;
  141.             asltags[6].ti_Data=atoi(freq->filebuf);
  142.         }
  143.         else {
  144.             if (freq->filebuf) {
  145.                 asltags[5].ti_Tag=ASL_File;
  146.                 asltags[5].ti_Data=(ULONG)freq->filebuf;
  147.             }
  148.             if (freq->dirbuf) {
  149.                 asltags[6].ti_Tag=ASL_Dir;
  150.                 asltags[6].ti_Data=(ULONG)freq->dirbuf;
  151.             }
  152.         }
  153.  
  154.         asltags[7].ti_Tag=ASL_FuncFlags;
  155.  
  156.         if (font) asltags[7].ti_Data=FONF_NEWIDCMP;
  157.         else {
  158.             if (freq->flags&DFRF_SAVE) asltags[7].ti_Data=FILF_SAVE|FILF_NEWIDCMP;
  159.             else if (freq->flags&DFRF_MULTI) asltags[7].ti_Data=FILF_MULTISELECT|FILF_NEWIDCMP;
  160.             else asltags[7].ti_Data=FILF_NEWIDCMP;
  161.  
  162.             if (freq->flags&DFRF_DIRREQ) {
  163.                 asltags[8].ti_Tag=ASL_ExtFlags1;
  164.                 asltags[8].ti_Data|=FIL1F_NOFILES;
  165.             }
  166.         }
  167.  
  168.         if (request=AllocAslRequest((font)?ASL_FontRequest:ASL_FileRequest,asltags)) {
  169.             if (res=AslRequest(request,NULL)) {
  170.                 if (font) {
  171.                     if (freq->dirbuf) {
  172.                         StrCombine(freq->dirbuf,"FONTS:",((struct FontRequester *)request)->fo_Attr.ta_Name,256);
  173.                         strcat(freq->dirbuf,"/");
  174.                     }
  175.                     if (freq->filebuf) {
  176.                         LSprintf(freq->filebuf,"%ld",((struct FontRequester *)request)->fo_Attr.ta_YSize);
  177.                     }
  178.                 }
  179.                 else {
  180.                     fr=(struct FileRequester *)request;
  181.                     if (freq->dirbuf) strcpy(freq->dirbuf,fr->fr_Drawer);
  182.                     if (!(freq->flags&DFRF_DIRREQ)) {
  183.                         if (freq->filebuf) strcpy(freq->filebuf,fr->fr_File);
  184.                     }
  185.                     if (freq->flags&DFRF_MULTI && fr->fr_NumArgs>0) {
  186.                         if ((freq->filearray=
  187.                             LAllocRemember(&freq->filearraykey,(fr->fr_NumArgs+1)*4,MEMF_CLEAR))) {
  188.                             for (a=0;a<fr->fr_NumArgs;a++) {
  189.                                 if (freq->filearray[a]=LAllocRemember(&freq->filearraykey,
  190.                                     strlen(fr->fr_ArgList[a].wa_Name)+1,MEMF_CLEAR)) {
  191.                                     strcpy(freq->filearray[a],fr->fr_ArgList[a].wa_Name);
  192.                                 }
  193.                             }
  194.                         }
  195.                     }
  196.                 }
  197.             }
  198.             FreeAslRequest(request);
  199.         }
  200.         CloseLibrary(AslBase);
  201.         return(res);
  202.     }
  203.     else {
  204.         ULONG class;
  205.         USHORT code,gadgetid,qual;
  206.         struct FileReqData *freqdata;
  207.         unsigned char *dirbuf;
  208.         int i,ret=1;
  209.  
  210.         if (!(freqdata=AllocMem(sizeof(struct FileReqData),MEMF_CLEAR)))
  211.             return(ERROR_NOMEM);
  212.         freqdata->freq=freq;
  213.         if (!(initrequester(freqdata))) {
  214.             close_req(freqdata);
  215.             return(ERROR_NOMEM);
  216.         }
  217.         dirbuf=freq->dirbuf;
  218.  
  219.         if ((i=get_filenames(freqdata))==CANCEL) {
  220.             close_req(freqdata);
  221.             freemulti(freq);
  222.             return(ERROR_CANCEL);
  223.         }
  224.         if (i!=OKAY) {
  225.             FOREVER {
  226.                 Wait(1<<freqdata->fr_Window->UserPort->mp_SigBit);
  227.                 while (getintuimsg(freqdata->fr_Window,&class,&code,&qual,&gadgetid)) {
  228.                     if ((i=do_idcmp(freqdata,class,code,qual,gadgetid))==CANCEL) {
  229.                         close_req(freqdata);
  230.                         freemulti(freq);
  231.                         return(ERROR_CANCEL);
  232.                     }
  233.                     if (i==OKAY) {
  234.                         close_req(freqdata);
  235.                         goto acceptreq;
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.         else close_req(freqdata);
  241. acceptreq:
  242.         checkdrawer(dirbuf);
  243.         if (freq->flags&DFRF_DIRREQ) {
  244.             if (i==OKAY || dirbuf[0]) ret=1;
  245.             else ret=0;
  246.         }
  247.         return(ret);
  248.     }
  249. }
  250.  
  251. void close_req(freqdata)
  252. struct FileReqData *freqdata;
  253. {
  254.     struct direntry *file;
  255.     struct DOpusFileReq *freq;
  256.     char *buf;
  257.     int b;
  258.  
  259.     if (freqdata) {
  260.         freq=freqdata->freq;
  261.         if (freqdata->fr_Window) {
  262.             freqdata->freq->x=freqdata->fr_Window->LeftEdge;
  263.             freqdata->freq->y=freqdata->fr_Window->TopEdge;
  264.             CloseWindow(freqdata->fr_Window);
  265.         }
  266.         if (freqdata->flags&DFRF_MULTI && (file=freqdata->firstfile)) {
  267.             b=1;
  268.             while (file) {
  269.                 if (file->select) ++b;
  270.                 file=file->next;
  271.             }
  272.             if (freq->filearray=(char **)DoAllocRemember(&freq->filearraykey,sizeof(char *)*b,MEMF_CLEAR)) {
  273.                 if (buf=(char *)DoAllocRemember(&freq->filearraykey,b*32,MEMF_CLEAR)) {
  274.                     file=freqdata->firstfile; b=0;
  275.                     while (file) {
  276.                         if (file->select) {
  277.                             freq->filearray[b]=&buf[b*32];
  278.                             strcpy(freq->filearray[b],file->name);
  279.                             ++b;
  280.                         }
  281.                         file=file->next;
  282.                     }
  283.                     freq->filearray[b]=&buf[b*32];
  284.                     freq->filearray[b][0]=0;
  285.                 }
  286.                 else freemulti(freq);
  287.             }
  288.         }
  289.         deallocate_entries(freqdata);
  290.         if (freqdata->filetype)
  291.             FreeMem(freqdata->filetype,sizeof(int)*freqdata->freq->lines);
  292.         if (freqdata->finfo) FreeMem(freqdata->finfo,sizeof(struct FileInfoBlock));
  293.         FreeMem(freqdata,sizeof(struct FileReqData));
  294.     }
  295. }
  296.  
  297. displayfiles(freqdata)
  298. struct FileReqData *freqdata;
  299. {
  300.     struct direntry *work;
  301.     struct RastPort *rp;
  302.     int a,b,y,nlim,slim;
  303.  
  304.     if (freqdata->fileoffset==freqdata->oldfileoffset) return(0);
  305.     freqdata->oldfileoffset=freqdata->fileoffset;
  306.     if ((work=freqdata->firstfile)) {
  307.         for (a=0;a<freqdata->fileoffset;a++)
  308.             if (!(work=work->next)) break;
  309.     }
  310.     rp=freqdata->fr_Window->RPort;
  311.  
  312.     y=freqdata->fy+freqdata->fb;
  313.     nlim=freqdata->width-7; slim=7;
  314.     if (nlim<8) {
  315.         nlim=8;
  316.         slim=freqdata->width-8;
  317.     }
  318.     if (nlim>freqdata->width) {
  319.         nlim=freqdata->width;
  320.         slim=0;
  321.     }
  322.     SetDrMd(rp,JAM2);
  323.     for (b=0;b<freqdata->freq->lines;b++) {
  324.         Move(rp,10,y);
  325.         if (work) {
  326.             freqdata->filetype[b]=work->type;
  327.             if (work->type<0) {
  328.                 if (work->select) {
  329.                     SetAPen(rp,2);
  330.                     SetBPen(rp,3);
  331.                 }
  332.                 else SetAPen(rp,1);
  333.             }
  334.             else if (work->type>0) SetAPen(rp,3);
  335.             else SetAPen(rp,2);
  336.             a=strlen(work->name); if (a>nlim) a=nlim;
  337.             Text(rp,work->name,a);
  338.             if (a<nlim) Text(rp,nullstring,nlim-a);
  339.             if (slim) Text(rp,work->size,slim);
  340.             if (work->select) SetBPen(rp,0);
  341.             work=work->next;
  342.         }
  343.         else Text(rp,nullstring,freqdata->width);
  344.         y+=freqdata->fh;
  345.     }
  346. }
  347.  
  348. void deallocate_entries(freqdata)
  349. struct FileReqData *freqdata;
  350. {
  351.     DoFreeRemember(&freqdata->filekey);
  352.     freqdata->firstfile=freqdata->firstdir=NULL;
  353.     freqdata->fileentries=freqdata->fileoffset=0; freqdata->oldfileoffset=-1;
  354. }
  355.  
  356. void doposprop(freqdata)
  357. struct FileReqData *freqdata;
  358. {
  359.     freqdata->fileoffset=DoGetSliderPos(&freqdata->reqgads[8],freqdata->fileentries,freqdata->freq->lines);
  360.     displayfiles(freqdata);
  361. }
  362.  
  363. get_filenames(freqdata)
  364. struct FileReqData *freqdata;
  365. {
  366.     BPTR lock;
  367.     ULONG class;
  368.     USHORT code,qual,gadgetid;
  369.     int ret=0;
  370.     char buf[33];
  371.  
  372.     freqdata->firstfile=freqdata->firstdir=NULL;
  373.  
  374.     if (!(lock=Lock(freqdata->freq->dirbuf,ACCESS_READ))) {
  375.         freqdata->oldfileoffset=-1; freqdata->fileentries=0;
  376.         fixprop(freqdata);
  377.         displayfiles(freqdata);
  378.         return(0);
  379.     }
  380.  
  381.     Examine(lock,freqdata->finfo);
  382.     if (freqdata->finfo->fib_DirEntryType<0) {
  383.         UnLock(lock);
  384.         freqdata->oldfileoffset=-1;
  385.         displayfiles(freqdata);
  386.         return(0);
  387.     }
  388.  
  389.     while (ExNext(lock,freqdata->finfo)) {
  390.         while (getintuimsg(freqdata->fr_Window,&class,&code,&qual,&gadgetid)) {
  391.             ret=gettingdirmsg(freqdata,class,code,qual,gadgetid);
  392.             if (ret==OKAY || ret==CANCEL || ret==INTERRUPT) {
  393.                 if (lock) UnLock(lock);
  394.                 return(ret);
  395.             }
  396.         }
  397.         if (freqdata->finfo->fib_DirEntryType<0) {
  398.             if (freqdata->flags&DFRF_FONT) {
  399.                 LSprintf(buf,"%ld",atoi(freqdata->finfo->fib_FileName));
  400.                 if (strcmp(buf,freqdata->finfo->fib_FileName)) continue;
  401.             }
  402.             else if (freqdata->flags&DFRF_DIRREQ) continue;
  403.         }
  404.         addfileentry(freqdata,freqdata->finfo->fib_FileName,
  405.             freqdata->finfo->fib_DirEntryType,freqdata->finfo->fib_Size);
  406.         freqdata->oldfileoffset=-1;
  407.         fixprop(freqdata);
  408.         doposprop(freqdata);
  409.     }
  410.     if (lock) UnLock(lock);
  411.     freqdata->oldfileoffset=-1;
  412.     displayfiles(freqdata);
  413.     return(ret);
  414. }
  415.  
  416. getnewdrawer(freqdata)
  417. struct FileReqData *freqdata;
  418. {
  419.     checkdrawer(freqdata->freq->dirbuf);
  420.     refreshdrawergad(freqdata);
  421.     activatefilegad(freqdata);
  422.     clearfiles(freqdata);
  423.     return(get_filenames(freqdata));
  424. }
  425.  
  426. void clearfiles(freqdata)
  427. struct FileReqData *freqdata;
  428. {
  429.     deallocate_entries(freqdata);
  430.     doprops(freqdata);
  431.     fixprop(freqdata);
  432.     displayfiles(freqdata);
  433. }
  434.  
  435. getnew_file(freqdata,work)
  436. struct FileReqData *freqdata;
  437. struct direntry *work;
  438. {
  439.     int i,b;
  440.  
  441.     if (work->type>0) {
  442.         TackOn(freqdata->freq->dirbuf,work->name,256);
  443.         i=getnewdrawer(freqdata);
  444.         if (i!=OKAY && i!=CANCEL && i!=INTERRUPT) i=INTERRUPT;
  445.         return(i);
  446.     }
  447.     if (work->type==0) {
  448.         strcpy(freqdata->freq->dirbuf,work->name);
  449.         i=getnewdrawer(freqdata);
  450.         if (i!=OKAY && i!=CANCEL && i!=INTERRUPT) i=INTERRUPT;
  451.         return(i);
  452.     }
  453.     if ((strcmp(freqdata->freq->filebuf,work->name))==0) b=1;
  454.     else b=0;
  455.     strcpy(freqdata->freq->filebuf,work->name);
  456.     RefreshGList(&freqdata->reqgads[0],freqdata->fr_Window,NULL,1);
  457.     return(b);
  458. }
  459.  
  460. do_idcmp(freqdata,class,code,qual,gadgetid)
  461. struct FileReqData *freqdata;
  462. ULONG class;
  463. USHORT code,qual,gadgetid;
  464. {
  465.     int ret=0,x,y,a,b,ty;
  466.     struct RastPort *rp;
  467.     struct direntry *file;
  468.     LONG sec,mic;
  469.  
  470.     switch (class) {
  471.         case IDCMP_GADGETDOWN:
  472.             switch (gadgetid) {
  473.                 case FILENAMEPOS:
  474.                     doposprop(freqdata);
  475.                     FOREVER {
  476.                         Wait(1<<freqdata->fr_Window->UserPort->mp_SigBit);
  477.                         while (getintuimsg(freqdata->fr_Window,&class,&code,&qual,&gadgetid)) {
  478.                             if (class==GADGETUP) break;
  479.                             if (class==MOUSEMOVE) doposprop(freqdata);
  480.                         }
  481.                         if (class==GADGETUP) break;
  482.                     }
  483.                     break;
  484.                 case FILENAMEUP:
  485.                     repeatscroll(freqdata,-1,0);
  486.                     break;
  487.                 case FILENAMEDOWN:
  488.                     repeatscroll(freqdata,1,0);
  489.                     break;
  490.             }
  491.             activatefilegad(freqdata);
  492.             return(0);
  493.         case IDCMP_GADGETUP:
  494.             switch (gadgetid) {
  495.                 case FILENAMEPOS:
  496.                     doposprop(freqdata);
  497.                     break;
  498.                 case CANCEL:
  499.                     ret=CANCEL;
  500.                     break;
  501.                 case FILENAME:
  502.                     if (qual&IEQUALIFIER_LSHIFT || qual&IEQUALIFIER_RSHIFT) {
  503.                         activatestrgad(freqdata->fr_Window,&freqdata->reqgads[1]);
  504.                         return(-1);
  505.                     }
  506.                     ret=OKAY;
  507.                     break;
  508.                 case OKAY:
  509.                     ret=OKAY;
  510.                     break;
  511.                 case DRAWERNAME:
  512.                     refreshdrawergad(freqdata);
  513.                     if (qual&IEQUALIFIER_LSHIFT || qual&IEQUALIFIER_RSHIFT) {
  514.                         activatefilegad(freqdata);
  515.                         return(-1);
  516.                     }
  517.                     if ((ret=getnewdrawer(freqdata))!=OKAY && ret!=CANCEL && ret!=INTERRUPT)
  518.                         ret=INTERRUPT;
  519.                     return(ret);
  520.                 case PARENT:
  521.                     if (doparent(freqdata)) {
  522.                         if ((ret=getnewdrawer(freqdata))!=OKAY && ret!=CANCEL && ret!=INTERRUPT)
  523.                             ret=INTERRUPT;
  524.                     }
  525.                     break;
  526.                 case DRIVES:
  527.                     activatefilegad(freqdata);
  528.                     if ((ret=listdevices(freqdata))!=OKAY && ret!=CANCEL && ret!=INTERRUPT)
  529.                         ret=INTERRUPT;
  530.                     break;
  531.             }
  532.             activatefilegad(freqdata);
  533.             return(ret);
  534.             break;
  535.         case IDCMP_MOUSEBUTTONS:
  536.             x=freqdata->fr_Window->MouseX; y=freqdata->fr_Window->MouseY;
  537.             if (code==SELECTDOWN &&
  538.                 x>9 && x<freqdata->ww+10 && y>=freqdata->fy && y<freqdata->fy+(freqdata->freq->lines*freqdata->fh)) {
  539.                 a=(y-freqdata->fy)/freqdata->fh;
  540.                 if (file=getfileentry(freqdata,a)) {
  541.                     b=1; ty=freqdata->fy+(a*freqdata->fh);
  542.                     rp=freqdata->fr_Window->RPort;
  543.                     SetDrMd(rp,COMPLEMENT);
  544.                     RectFill(rp,10,ty,freqdata->ww+9,ty+(freqdata->fh-1));
  545.                     if (freqdata->flags&DFRF_MULTI && file->type<0) {
  546.                         file->select=1-file->select;
  547.                         b=1;
  548.                     }
  549.                     else {
  550.                         freqdata->fr_Window->Flags|=WFLG_REPORTMOUSE;
  551.                         FOREVER {
  552.                             Wait(1<<freqdata->fr_Window->UserPort->mp_SigBit);
  553.                             while (getintuimsg(freqdata->fr_Window,&class,&code,&qual,&gadgetid)) {
  554.                                 if (class==MOUSEMOVE) {
  555.                                     x=freqdata->fr_Window->MouseX; y=freqdata->fr_Window->MouseY;
  556.                                     if (x<10 || x>freqdata->ww+9 || y<ty || y>=ty+freqdata->fh) {
  557.                                         if (b) {
  558.                                             b=0;
  559.                                             RectFill(rp,10,ty,freqdata->ww+9,ty+(freqdata->fh-1));
  560.                                         }
  561.                                     }
  562.                                     else if (!b) {
  563.                                         b=1;
  564.                                         RectFill(rp,10,ty,freqdata->ww+9,ty+(freqdata->fh-1));
  565.                                     }
  566.                                 }
  567.                                 else if (class==MOUSEBUTTONS && code==SELECTUP) break;
  568.                             }
  569.                             if (class==MOUSEBUTTONS && code==SELECTUP) break;
  570.                         }
  571.                         freqdata->fr_Window->Flags&=~WFLG_REPORTMOUSE;
  572.                     }
  573.                     if (b) {
  574.                         if (!(freqdata->flags&DFRF_MULTI))
  575.                             RectFill(rp,10,ty,freqdata->ww+9,ty+(freqdata->fh-1));
  576.                         SetDrMd(rp,JAM2);
  577.                         CurrentTime((ULONG *)&sec,(ULONG *)&mic);
  578.                         if ((ret=getnew_file(freqdata,file))==1 &&
  579.                             DoubleClick(freqdata->prevsec,freqdata->prevmic,sec,mic)) ret=OKAY;
  580.                         else if (ret!=OKAY && ret!=CANCEL && ret!=INTERRUPT) {
  581.                             freqdata->prevsec=sec; freqdata->prevmic=mic;
  582.                             ret=0;
  583.                         }
  584.                     }
  585.                     else SetDrMd(rp,JAM2);
  586.                 }
  587.             }
  588.             else if (code==MENUDOWN &&
  589.                 x>9 && x<freqdata->ww+10 && y>28 && y<37+(freqdata->freq->lines*freqdata->fh)) {
  590.                 a=((freqdata->freq->lines*freqdata->fh)/2)+30;
  591.                 if (y<(a-freqdata->fh)) b=-1;
  592.                 else if (y>(a+freqdata->fh)) b=1;
  593.                 else b=0;
  594.                 repeatscroll(freqdata,b,1);
  595.             }
  596.             activatefilegad(freqdata);
  597.             return(ret);
  598.             break;
  599.         default:
  600.             activatefilegad(freqdata);
  601.             break;
  602.     }
  603.     return(0);
  604. }
  605.  
  606. listdevices(freqdata)
  607. struct FileReqData *freqdata;
  608. {
  609.     char devname[32];
  610.     struct DeviceList *devlist;
  611.     struct RootNode *rootnode;
  612.     struct DosInfo *dosinfo;
  613.     ULONG class;
  614.     USHORT code,qual,gadgetid;
  615.     int ret;
  616.  
  617.     clearfiles(freqdata);
  618.     rootnode=(struct RootNode *) DOSBase->dl_Root;
  619.     dosinfo=(struct DosInfo *) BADDR(rootnode->rn_Info);
  620.     devlist=(struct DeviceList *) BADDR(dosinfo->di_DevInfo);
  621.  
  622.     while (devlist) {
  623.         while (getintuimsg(freqdata->fr_Window,&class,&code,&qual,&gadgetid)) {
  624.             ret=gettingdirmsg(freqdata,class,code,qual,gadgetid);
  625.             if (ret==OKAY || ret==CANCEL || ret==INTERRUPT) return(ret);
  626.         }
  627.         if (devlist->dl_Type!=DLT_DEVICE || devlist->dl_Task) {
  628.             BtoCStr(devlist->dl_Name,devname,32);
  629.             LStrCat(devname,":");
  630.             addfileentry(freqdata,devname,0,devlist->dl_Type);
  631.         }
  632.         devlist=(struct DeviceList *) BADDR(devlist->dl_Next);
  633.     }
  634.     freqdata->oldfileoffset=-1;
  635.     fixprop(freqdata);
  636.     doposprop(freqdata);
  637.     return(-1);
  638. }
  639.  
  640. char *devtypes[5]={"  <DEV>","  <ASN>","  <VOL>","  <DFR>","  <NBD>"};
  641.  
  642. addfileentry(freqdata,name,type,size)
  643. struct FileReqData *freqdata;
  644. char *name;
  645. int type,size;
  646. {
  647.     struct direntry *add,*afterdir=NULL,*work,*new;
  648.     int adir=0;
  649.  
  650.     if (freqdata->firstfile) {
  651.         if (type<0) {
  652.             if (freqdata->firstdir) add=freqdata->firstdir;
  653.             else {
  654.                 add=freqdata->firstfile;
  655.                 while (add && add->type>0) add=add->next;
  656.             }
  657.         }
  658.         else add=freqdata->firstfile;
  659.         while (add) {
  660.             if (LStrCmpI(name,add->name)<=0 ||
  661.                 (type>0 && add==freqdata->firstdir)) {
  662.                 if (add->last) afterdir=add->last;
  663.                 else adir=1;
  664.                 break;
  665.             }
  666.             add=add->next;
  667.         }
  668.     }
  669.  
  670.     if (!(new=(struct direntry *)
  671.         DoAllocRemember(&freqdata->filekey,sizeof(struct direntry),MEMF_CLEAR)))
  672.         return(0);
  673.  
  674.     if (afterdir) {
  675.         work=afterdir;
  676.         add=afterdir->next;
  677.         work->next=new;
  678.         new->last=work;
  679.         work=new;
  680.         work->next=add;
  681.         add->last=work;
  682.     }
  683.     else if (adir==1) {
  684.         add=freqdata->firstfile;
  685.         work=new;
  686.         work->next=add;
  687.         add->last=work;
  688.         freqdata->firstfile=work;
  689.     }
  690.     else {
  691.         if (freqdata->firstfile) {
  692.             work=freqdata->firstfile;
  693.             while (work->next) work=work->next;
  694.             work->next=new;
  695.             new->last=work;
  696.             work=new;
  697.         }
  698.         else {
  699.             work=new;
  700.             freqdata->firstfile=work;
  701.         }
  702.     }
  703.     strcpy(work->name,name);
  704.     if (type==0) strcpy(work->size,devtypes[size]);
  705.     else if (type<0) {
  706.         LSprintf(work->size,"%7ld",size);
  707.         if ((work->last && work->last->type>0) || (!work->last && type<0))
  708.             freqdata->firstdir=work;
  709.     }
  710.     else strcpy(work->size,"    Dir");
  711.     work->type=type;
  712.     ++freqdata->fileentries;
  713. }
  714.  
  715. repeatscroll(freqdata,dir,menu)
  716. struct FileReqData *freqdata;
  717. int dir,menu;
  718. {
  719.     ULONG class;
  720.     USHORT code,gadgetid;
  721.     int x,y,m;
  722.  
  723.     if ((dir==-1 && freqdata->fileoffset==0) ||
  724.         (dir==1 && freqdata->fileoffset>=freqdata->fileentries-freqdata->freq->lines))
  725.         return(0);
  726.     freqdata->fileoffset+=dir;
  727.     displayfiles(freqdata);
  728.     doprops(freqdata);
  729.     if (menu) m=((freqdata->freq->lines*freqdata->fh)/2)+30;
  730.     Delay(5);
  731.     FOREVER {
  732.         if (getintuimsg(freqdata->fr_Window,&class,&code,NULL,&gadgetid) &&
  733.             (class==GADGETUP || (class==MOUSEBUTTONS && code==SELECTUP)) ||
  734.             (menu && class==MOUSEBUTTONS && code==MENUUP)) break;
  735.         if (menu) {
  736.             x=freqdata->fr_Window->MouseX; y=freqdata->fr_Window->MouseY;
  737.             if (x>9 && x<freqdata->ww+10) {
  738.                 if (y<(m-freqdata->fh)) dir=-1;
  739.                 else if (y>(m+freqdata->fh)) dir=1;
  740.                 else dir=0;
  741.             }
  742.         }
  743.         if ((dir==-1 && freqdata->fileoffset==0) ||
  744.             (dir==1 && freqdata->fileoffset>=freqdata->fileentries-freqdata->freq->lines))
  745.             break;
  746.         freqdata->fileoffset+=dir;
  747.         displayfiles(freqdata);
  748.         doprops(freqdata);
  749.     }
  750. }
  751.  
  752. void doprops(freqdata)
  753. struct FileReqData *freqdata;
  754. {
  755.     DoFixSliderPot(freqdata->fr_Window,&freqdata->reqgads[8],freqdata->fileoffset,freqdata->fileentries,freqdata->freq->lines,1);
  756. }
  757.  
  758. void fixprop(freqdata)
  759. struct FileReqData *freqdata;
  760. {
  761.     DoFixSliderBody(freqdata->fr_Window,&freqdata->reqgads[8],freqdata->fileentries,freqdata->freq->lines,1);
  762. }
  763.  
  764. doparent(freqdata)
  765. struct FileReqData *freqdata;
  766. {
  767.     int i,b;
  768.  
  769.     if ((i=strlen(freqdata->freq->dirbuf))<2) return(0);
  770.     --i;
  771.     if (freqdata->freq->dirbuf[i]==':') return(0);
  772.     if (freqdata->freq->dirbuf[i]=='/') --i;
  773.     for (b=i;b>-1;b--) {
  774.         if (freqdata->freq->dirbuf[b]=='/') break;
  775.         if (freqdata->freq->dirbuf[b]==':') { ++b; break; }
  776.     }
  777.     if (b<0) b=0;
  778.     freqdata->freq->dirbuf[b]=0;
  779.     RefreshGList(&freqdata->reqgads[1],freqdata->fr_Window,NULL,1);
  780.     return(1);
  781. }
  782.  
  783. void checkdrawer(buf)
  784. char *buf;
  785. {
  786.     int i;
  787.  
  788.     if ((i=strlen(buf))>1) {
  789.         --i;
  790.         if (buf[i]!='/' && buf[i]!=':') LStrCat(buf,"/");
  791.     }
  792. }
  793.  
  794. void refreshdrawergad(freqdata)
  795. struct FileReqData *freqdata;
  796. {
  797.     freqdata->drawernamesinfo.BufferPos=strlen(freqdata->freq->dirbuf);
  798.     RefreshGList(&freqdata->reqgads[1],freqdata->fr_Window,NULL,1);
  799. }
  800.  
  801. void activatestrgad(win,gad)
  802. struct Window *win;
  803. struct Gadget *gad;
  804. {
  805.     struct StringInfo *sinfo;
  806.  
  807.     sinfo=(struct StringInfo *)gad->SpecialInfo;
  808.     sinfo->BufferPos=strlen((char *)sinfo->Buffer);
  809.     RefreshGList(gad,win,NULL,1);
  810.     ActivateGadget(gad,win,NULL);
  811. }
  812.  
  813. initrequester(freqdata)
  814. struct FileReqData *freqdata;
  815. {
  816.     int a,b;
  817.     struct DOpusFileReq *freq;
  818.     struct RastPort *rp;
  819.     struct Screen *screen;
  820.     struct TextFont *font;
  821.  
  822.     freq=freqdata->freq;
  823.     freq->filearraykey=NULL; freq->filearray=NULL;
  824.     freqdata->flags=freq->flags;
  825.     if (freqdata->flags&DFRF_DIRREQ) freqdata->flags&=~DFRF_MULTI;
  826.  
  827.     if (IntuitionBase->LibNode.lib_Version>35) freqdata->version2=1;
  828.     screen=(freq->window)?freq->window->WScreen:IntuitionBase->ActiveScreen;
  829.  
  830.     freqdata->sfh=screen->RastPort.Font->tf_YSize;
  831.     freqdata->sfw=screen->RastPort.Font->tf_XSize;
  832.     if (freqdata->sfh<8) freqdata->sfh=8;
  833.     if (freqdata->sfw<6) freqdata->sfw=6;
  834.  
  835.     if (screen->RastPort.Font->tf_Flags&FPF_PROPORTIONAL)
  836.         font=GfxBase->DefaultFont;
  837.     else font=screen->RastPort.Font;
  838.  
  839.     freqdata->fh=font->tf_YSize; freqdata->fw=font->tf_XSize;
  840.     freqdata->fb=font->tf_Baseline;
  841.  
  842.     CopyMem((char *)&defaultprop,(char *)&freqdata->filenameprop,sizeof(struct PropInfo));
  843.     freqdata->filenamesinfo.Buffer=(STRPTR)freq->filebuf;
  844.     freqdata->filenamesinfo.MaxChars=31;
  845.     freqdata->drawernamesinfo.Buffer=(STRPTR)freq->dirbuf;
  846.     freqdata->drawernamesinfo.MaxChars=236;
  847.  
  848.     if (freq->lines<5) freq->lines=5;
  849.     else if (freq->lines>((screen->Height-(freqdata->sfh*5)+35)/freqdata->fh))
  850.         freq->lines=(screen->Height-(freqdata->sfh*5)+35)/freqdata->fh;
  851.  
  852.     if (!(freqdata->filetype=AllocMem(sizeof(int)*freq->lines,MEMF_CLEAR)))
  853.         return(0);
  854.  
  855.     CopyMem((char *)&defaultgadgets,(char *)&freqdata->reqgads,sizeof(struct Gadget)*9);
  856.     CopyMem((char *)&defaulttext,(char *)&freqdata->reqtext,sizeof(struct IntuiText)*6);
  857.     CopyMem((char *)&defaultimage,(char *)&freqdata->filenameimage,sizeof(struct Image));
  858.     freqdata->reqgads[0].SpecialInfo=(APTR)&freqdata->filenamesinfo;
  859.     freqdata->reqgads[1].SpecialInfo=(APTR)&freqdata->drawernamesinfo;
  860.     freqdata->reqgads[8].GadgetRender=(APTR)&freqdata->filenameimage;
  861.     freqdata->reqgads[8].SpecialInfo=(APTR)&freqdata->filenameprop;
  862.     for (a=0;a<8;a++) freqdata->reqgads[a].NextGadget=&freqdata->reqgads[a+1];
  863.     for (a=0;a<4;a++) freqdata->reqgads[a].GadgetText=&freqdata->reqtext[a];
  864.     for (a=6;a<8;a++) freqdata->reqgads[a].GadgetText=&freqdata->reqtext[a-2];
  865.     CopyMem((char *)&defaultwindow,(char *)&freqdata->reqwin,sizeof(struct NewWindow));
  866.     freqdata->reqwin.Height=(freq->lines*freqdata->fh)+(freqdata->sfh*5)+31+((freqdata->flags&DFRF_DIRREQ)?0:4);
  867.     if (freqdata->reqwin.Height>screen->Height) {
  868.         freq->lines=(screen->Height-((freqdata->sfh*5)+35))/freqdata->fh;
  869.         freqdata->reqwin.Height=(freq->lines*freqdata->fh)+(freqdata->sfh*5)+35;
  870.     }
  871.     if (freqdata->flags&DFRF_DIRREQ) freqdata->reqwin.Height-=freqdata->sfh+2;
  872.     freqdata->reqwin.Width=(freqdata->fw*35)+36;
  873.     if (freqdata->reqwin.Width>screen->Width) {
  874.         a=(screen->Width-36)/freqdata->fw;
  875.         freqdata->width=a;
  876.         freqdata->reqwin.Width=(freqdata->fw*a)+36;
  877.     }
  878.     else freqdata->width=35;
  879.     freqdata->ww=freqdata->width*freqdata->fw;
  880.  
  881.     freqdata->reqwin.Screen=screen;
  882.     if (freq->x==-2) freqdata->reqwin.LeftEdge=(screen->Width-freqdata->reqwin.Width)/2;
  883.     else if (freq->x<0) freqdata->reqwin.LeftEdge=15;
  884.     else freqdata->reqwin.LeftEdge=freq->x;
  885.     if (freq->y==-2) freqdata->reqwin.TopEdge=(screen->Height-freqdata->reqwin.Height)/2;
  886.     else if (freq->y<0) freqdata->reqwin.TopEdge=25;
  887.     else freqdata->reqwin.TopEdge=freq->y;
  888.     if (freqdata->reqwin.LeftEdge+freqdata->reqwin.Width>screen->Width)
  889.         freqdata->reqwin.LeftEdge=screen->Width-freqdata->reqwin.Width;
  890.     if (freqdata->reqwin.TopEdge+freqdata->reqwin.Height>screen->Height)
  891.         freqdata->reqwin.TopEdge=screen->Height-freqdata->reqwin.Height;
  892.     if (freq->title) freqdata->reqwin.Title=(STRPTR)freq->title;
  893.     else freqdata->reqwin.Title=(STRPTR)"File request";
  894.     if (freqdata->flags&DFRF_SAVE && !freqdata->version2) freqdata->reqwin.BlockPen=2;
  895.  
  896.     if (!(freqdata->finfo=AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR)))
  897.         return(0);
  898.  
  899.     freqdata->oldfileoffset=-1;
  900.  
  901.     if (!(freqdata->fr_Window=OpenWindow(&freqdata->reqwin))) return(0);
  902.     rp=freqdata->fr_Window->RPort;
  903.     SetFont(rp,font);
  904.     SetDrMd(rp,JAM2);
  905.     freqdata->sfy=freqdata->fr_Window->BorderTop+2;
  906.     freqdata->fy=freqdata->sfy+freqdata->sfh+7;
  907.  
  908.     a=freq->lines*freqdata->fh;
  909.     freqdata->reqgads[1].TopEdge=freqdata->fy+a+5;
  910.     if (!(freqdata->flags&DFRF_DIRREQ))
  911.         freqdata->reqgads[0].TopEdge=freqdata->reqgads[1].TopEdge+freqdata->sfh+6;
  912.     freqdata->reqgads[2].TopEdge=
  913.         freqdata->reqgads[(freqdata->flags&DFRF_DIRREQ?1:0)].TopEdge+freqdata->sfh+4;
  914.     freqdata->reqgads[3].TopEdge=freqdata->reqgads[2].TopEdge;
  915.     freqdata->reqgads[4].TopEdge=freqdata->fy+a-15;
  916.     freqdata->reqgads[5].TopEdge=freqdata->fy+a-7;
  917.     freqdata->reqgads[6].TopEdge=freqdata->reqgads[7].TopEdge=freqdata->sfy;
  918.     freqdata->reqgads[8].TopEdge=freqdata->fy+1;
  919.     freqdata->reqgads[0].LeftEdge=freqdata->reqgads[1].LeftEdge=(freqdata->sfw*6)+16;
  920.     freqdata->reqgads[3].LeftEdge=freqdata->reqgads[7].LeftEdge=freqdata->ww-104;
  921.     freqdata->reqgads[4].LeftEdge=freqdata->reqgads[5].LeftEdge=freqdata->ww+12;
  922.     freqdata->reqgads[8].LeftEdge=freqdata->ww+16;
  923.     freqdata->reqgads[0].Width=freqdata->reqgads[1].Width=(freqdata->ww+24)-freqdata->reqgads[0].LeftEdge;
  924.     if ((freqdata->sfw*6)>132) {
  925.         freqdata->reqgads[2].Width=freqdata->reqgads[3].Width=
  926.             freqdata->reqgads[6].Width=freqdata->reqgads[7].Width=
  927.             freqdata->sfw*7;
  928.         freqdata->reqgads[3].LeftEdge-=((freqdata->sfw*7)-132);
  929.         freqdata->reqgads[7].LeftEdge=freqdata->reqgads[3].LeftEdge;
  930.     }
  931.     freqdata->reqgads[0].Height=freqdata->reqgads[1].Height=freqdata->sfh;
  932.     freqdata->reqgads[2].Height=freqdata->reqgads[3].Height=
  933.         freqdata->reqgads[6].Height=freqdata->reqgads[7].Height=freqdata->sfh+4;
  934.     freqdata->reqgads[8].Height=a-18;
  935.  
  936.     for (b=2;b<8;b++)
  937.         Do3DBox(rp,freqdata->reqgads[b].LeftEdge+2,freqdata->reqgads[b].TopEdge+1,
  938.             freqdata->reqgads[b].Width-4,freqdata->reqgads[b].Height-2,2,1);
  939.     if (!(freqdata->flags&DFRF_DIRREQ))
  940.         Do3DStringBox(rp,freqdata->reqgads[0].LeftEdge,freqdata->reqgads[0].TopEdge,freqdata->reqgads[0].Width,freqdata->sfh,2,1);
  941.     Do3DStringBox(rp,freqdata->reqgads[1].LeftEdge,freqdata->reqgads[1].TopEdge,freqdata->reqgads[1].Width,freqdata->sfh,2,1);
  942.     for (b=4;b<6;b++) DoArrow(rp,freqdata->ww+14,freqdata->reqgads[b].TopEdge+1,12,6,1,0,b-4);
  943.     Do3DBox(rp,10,freqdata->fy,freqdata->ww,a,2,1);
  944.     Do3DBox(rp,freqdata->ww+14,freqdata->fy,12,a-16,2,1);
  945.  
  946.     freqdata->reqtext[0].LeftEdge=freqdata->reqtext[1].LeftEdge=-(freqdata->reqgads[0].LeftEdge-10);
  947.     for (b=2;b<6;b++) freqdata->reqtext[b].LeftEdge=(freqdata->reqgads[2].Width-(freqdata->sfw*6))/2;
  948.  
  949.     AddGList(freqdata->fr_Window,&freqdata->reqgads[(freqdata->flags&DFRF_DIRREQ)?1:0],-1,-1,NULL);
  950.     RefreshGList(&freqdata->reqgads[(freqdata->flags&DFRF_DIRREQ)?1:0],freqdata->fr_Window,NULL,-1);
  951.     activatefilegad(freqdata);
  952.     return(1);
  953. }
  954.  
  955. getintuimsg(win,class,code,qual,gadgetid)
  956. struct Window *win;
  957. ULONG *class;
  958. USHORT *code,*qual,*gadgetid;
  959. {
  960.     struct IntuiMessage *msg;
  961.  
  962.     if (msg=(struct IntuiMessage *)GetMsg(win->UserPort)) {
  963.         *class=msg->Class; *code=msg->Code;
  964.         if (qual) *qual=msg->Qualifier;
  965.         if (msg->Class==GADGETDOWN || msg->Class==GADGETUP)
  966.             *gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  967.         ReplyMsg((struct Message *)msg);
  968.         return(1);
  969.     }
  970.     return(0);
  971. }
  972.  
  973. gettingdirmsg(freqdata,class,code,qual,gadgetid)
  974. struct FileReqData *freqdata;
  975. ULONG class;
  976. USHORT code,qual,gadgetid;
  977. {
  978.     int ret;
  979.  
  980.     if ((ret=do_idcmp(freqdata,class,code,qual,gadgetid))!=-1) {
  981.         freqdata->oldfileoffset=-1;
  982.         return(ret);
  983.     }
  984.     return(0);
  985. }
  986.  
  987. void activatefilegad(freqdata)
  988. struct FileReqData *freqdata;
  989. {
  990.     activatestrgad(freqdata->fr_Window,
  991.         &freqdata->reqgads[(freqdata->flags&DFRF_DIRREQ)?1:0]);
  992. }
  993.  
  994. struct direntry *getfileentry(freqdata,which)
  995. struct FileReqData *freqdata;
  996. int which;
  997. {
  998.     int i,b;
  999.     struct direntry *work;
  1000.  
  1001.     i=freqdata->fileoffset+which;
  1002.     if (!(work=freqdata->firstfile)) return(0);
  1003.     for (b=0;b<i;b++) if (!(work=work->next)) return(0);
  1004.     return(work);
  1005. }
  1006.  
  1007. void freemulti(freq)
  1008. struct DOpusFileReq *freq;
  1009. {
  1010.     if (freq->flags&DFRF_MULTI) DoFreeRemember(&freq->filearraykey);
  1011.     freq->filearray=NULL;
  1012. }
  1013.